﻿using Castle.Core.Logging;
using Castle.MicroKernel.Registration;
using System;
using Yto.Common.Dependency;
using Yto.Modules;
using Yto.Unitwork;

namespace Yto
{
    public class Launch : IDisposable
    {
        private Launch(Type startupModule) : this(startupModule, CtnManager.Instance)
        {
        }
        private Launch(Type startupModule, ICtnManager ctnManager)
        {
            this.startupModule = startupModule;
            this.ctnManager = ctnManager;
            _logger = NullLogger.Instance;

            UnitworkRegistrar.Initialize(ctnManager);
        }

        public static Launch Startup<T>(ICtnManager ctnManager)
            where T : BaseModule
        {
            return new Launch(typeof(T),ctnManager);
        }

        private Type startupModule;
        private ICtnManager ctnManager;
        private ILogger _logger;
        private bool IsDisposed;
        private IModuleManager _moduleManager;

        public void Dispose()
        {
            if (IsDisposed)
            {
                return;
            }
            IsDisposed = true;


        }

        public virtual void Initialize()
        {
            ResoverLogger();

            try
            {
                _logger.Info($"initialize start { DateTime.Now }");
                RegistLaunch();
                ctnManager.Container.Install(new CtnIntaller());

                _moduleManager = ctnManager.Resolver<IModuleManager>();
                _moduleManager.Initialize(startupModule);

                _moduleManager.StartModules();
            }
            catch (Exception e)
            {
                _logger.Fatal(e.Message, e);
                throw;
            }
        }

        private void ResoverLogger()
        {
            if (ctnManager.IsRegisted<ILoggerFactory>())
            {
                _logger = ctnManager.Resolver<ILoggerFactory>().Create(typeof(Launch));
            }
        }

        private void RegistLaunch()
        {
            if (!ctnManager.IsRegisted<Launch>())
            {
                ctnManager.Container.Register(
                    Component.For<Launch>().Instance(this));
            }
        }
    }
}
